// ProcessTable.h
//
// This class represents a singleton data structure to manage and update all data related to currently running
// processes and threads in nachos. This data will be updated on Fork and Exec when new processes and threads
// are launched. It will be used and updated in Exit to determine how to fully close down processes, threads,
// or possibly the whole system.
//
// Inaddition to how many processes and threads are currently running the table will manage parent-child
// hierarchies between them to make sure parents are not exited until all of their children are.

//#ifndef PROCTABLE_H
//#define PROCTABLE_H

#include "addrspace.h"
#include "table.h"
#include "thread.h"
#include "synch.h"

#define MAXNUMTHREADS (NumPhysPages*PageSize)/divRoundUp(UserStackSize,PageSize)
#define MAXNUMPROCESSES MAXNUMTHREADS

//KernelThreadEntry: one thread in the thread table
struct KernelThreadEntry {
	KernelThreadEntry();			// constructor
	~KernelThreadEntry();			// destructor
    unsigned int numChildThreads;	// number of child threads so that thread doesn't really exit until children have exited
    Thread* parentThread;			// parent thread to tell them we are exiting
    Lock* ExitLock;					// lock for securing data and for waiting for children threads to exit
    Condition* ExitCV;				// condition to wait for children to exit
    //bool isExiting;					// flag if this thread is exiting
};
//KernelProcessEntry: an entry for a process in the table
struct KernelProcessEntry {
	KernelProcessEntry();				// constructor
	~KernelProcessEntry();				// destructor
    unsigned int numChildProcesses;		//number of child processes
    AddrSpace* parentSpace;				//address space pointer of the parent space
	AddrSpace* currentSpace;			// address space pointer of the current process
    //BitMap* childProcessTableMap;		//bitmap for adding new childproc entries
    //ChildProcEntry* childProcesses;	//array of childproc entries
	Table* threadTable; 				// table of all threads (KernelThreadEntrys) in this process
    unsigned int numThreads;			//number of threads in this process
    Lock* dataLock;						//lock for securing data
    Condition* ExitCV;
};
/*
ProcessTable: a processTable.
Keeps track of all processes running in the system.
*/
class ProcessTable {
      public:
             /*addNewProc
             adds a new process entry and returns the spaceId of the entry
             the spaceId of the address space should be changed to the return value
             also, the parent relationship should be set manually
             */
             SpaceId addNewProcess(AddrSpace* space);
			 
             /*addNewThread
             adds a new thread entry to the process with the given id. returns the
			 threadId of the newly created thread entry.
             */
             ThreadId addNewThread(SpaceId id);
			 
             /*removeProccess
             removes the procEntry with the spaceId id.
             Parent relationships should be removed manually
             */
             void removeProcess(SpaceId id);
			 
             /*removeThread
             removes the threadEntry with the threadId id.
             Parent relationships should be removed manually
             */
             void removeThread(SpaceId processId, ThreadId threadId);
			 
             /*getProccess
             returns a pointer to the procEntry with the spaceId id if it is there
             if it is not there or if id is out of bounds, then the system will halt
             */
             KernelProcessEntry* getProcess(SpaceId id);
			 
             /*getThread
             returns a pointer to the threadEntry with the threadId id if it is there
             if it is not there or if id is out of bounds, then the system will halt
             */
             KernelThreadEntry* getThread(SpaceId spaceId, ThreadId threadId);
			 
            /*getNumProccesses
             returns the number of processes in the table.
             Used for determining the last thread
             */
             unsigned int getNumProcesses();
			 
			 /*setNumProccesses
             sets the number of current processes
             */
             void setNumProcesses(unsigned int num);
			 
			 /*incrementNumProccesses
             increases the number of processes by 1.
             */
             void incrementNumProcesses();
			 
			 /*decrementNumProccesses
             decreases the number of processes by 1.
             */
             void decrementNumProcesses();
			 
             /* Singleton accessor
			 will create a new processTable if there is not one currently build in the static pointer,
			 else it will return that pointer.
			 */
             static ProcessTable* getInstance();
			 
			 /* Singleton destructor
			 deletes the process table when the system is shutting down.
			 */
             static void deleteProcessTable();
			 
	  protected:
			ProcessTable();
			~ProcessTable();
			ProcessTable(const ProcessTable&);
			ProcessTable& operator= (const ProcessTable&);
			
      private:
			// Singleton pointer, will be returned by getInstance()
			static ProcessTable* instance;
            //The table of KernelProcessEntries in the process table
            Table* processTable;
			// lock to protect the process counter
			Lock* numProcessesLock;
            //number of processes in the table
            unsigned int numProcesses;
};
//#endif
